package org.ch03.hw.myarraylist;

import java.util.Arrays;

/**
 * @author ZJL
 * @date 2025-03-26
 */
public class MyArrayList<E> {

    /**
     * 默认初始容量
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 封装的数组
     */
    private Object[] elementData = {};

    /**
     * 数组实际使用的容量
     */
    private int size;

    /**
     * 缺省构造方法 - 实例化一个数组，默认大小为10
     */
    public MyArrayList() {
        this.elementData = new Object[DEFAULT_CAPACITY];
    }

    /**
     * 重载构造方法 - 实例化一个数组，大小的用户决定
     *
     * @param size
     */
    public MyArrayList(int size) {
        this.elementData = new Object[size];
    }

    /**
     * 添加元素
     *
     * @param e E类型的元素
     * @return 布尔值
     */
    public boolean add(E e) {
        // 1.判断是否需要扩容
        grow();
        // 2.添加元素
        this.elementData[size++] = e;
        return true;
    }

    /**
     * 实现数组扩容
     */
    private void grow() {
        if (size == this.elementData.length) {
            this.elementData = Arrays.copyOf(this.elementData, this.elementData.length * 2);
        }
    }

    /**
     * 数组实际的容量
     *
     * @return
     */
    public int size() {
        return this.size;
    }

    /**
     * 判断集合是否为空
     *
     * @return 当集合长度等于 0 时，返回 true 说明 集合为空
     */
    public boolean isEmpty() {
        return this.size == 0;
    }

    /**
     * 删除指定下标的元素
     *
     * @param index 下标
     * @return 删除的元素
     */
    public E remove(int index) {
        // 合法性验证
        checkIndex(index);
        // 获取删除的元素
        E oldElement = (E) this.elementData[index];
        // 删除元素
        System.arraycopy(this.elementData, index + 1, this.elementData, index, size - index - 1);
        // 最后一个元素设置为null 并更新实际容量
        this.elementData[--size] = null;
        return oldElement;
    }

    /**
     * 判断下标是否超出范围
     *
     * @param index 下标
     */
    private void checkIndex(int index) {
        if (index < 0 || index >= this.size) {
            throw new IndexOutOfBoundsException("下标索引越界，当前下标为" + index);
        }
    }

    /**
     * 给集合某个下标设置元素
     *
     * @param index   下标
     * @param element 数据
     */
    public E set(int index, E element) {
        // 合法性验证
        checkIndex(index);
        // 获取覆盖前之间的元素
        E oldElement = (E) this.elementData[index];
        //设置下标元素
        this.elementData[index] = element;
        return oldElement;
    }

    /**
     * 拿到数组下标对应的数据
     *
     * @param index 下标
     * @return 返回数据对应的类型
     */
    public E get(int index) {
        // 合法性验证
        checkIndex(index);
        return (E) this.elementData[index];
    }

    /**
     * 遍历循环数组里的元素
     * @return
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < size; i++) {
            sb.append(elementData[i]).append(",");
        }
        if (sb.length() == 1) {
            sb.append("]");
        } else {
            sb.setCharAt(sb.length() - 1, ']');
        }
        return sb.toString();
    }
}
